// import * as Cesium from "cesium"
const Event = Cesium.Event
const Material = Cesium.Material
const defined = Cesium.defined
const Color = Cesium.Color
const Cartesian2 = Cesium.Cartesian2
const Property = Cesium.Property
const defineProperties = Object.defineProperties
const createPropertyDescriptor = Cesium.createPropertyDescriptor
const source = `
#extension GL_OES_standard_derivatives : enable
czm_material czm_getMaterial(czm_materialInput materialInput){
  czm_material material = czm_getDefaultMaterial(materialInput);
  vec2 st = repeat * materialInput.st;
  vec4 colorImage = texture2D(image, vec2(fract(st.s - time), st.t));
  if(color.a == 0.0){
    discard;
  }else{
    material.alpha = colorImage.a * color.a;
    material.diffuse = colorImage.rgb;
  }
  return material;
}`
/**
 * @class AnimationMaterialProperty
 * @classdesc 动态材质类。
 * @param {Object} [options] optional 对象具有以下属性:
 * @param {Color} [options.color] 材质颜色。
 * @param {Boolean} [options.axisY] 材质流动方向是否为Y轴方向。
 * @param {Number} [options.duration] 材质流动的时间。
 * @param {Cartesian2} [options.repeat] 材质图案重复次数。
 * @param {String} [options.url] 材质图案路径。
 */
class AnimationMaterialProperty {
  constructor(options) {
    this._definitionChanged = new Event()
    this._color = undefined
    this._colorSubscription = undefined
    const opt = this._getOptions(options)

    this.color = opt.color
    this.axisY = opt.axisY

    this._time = new Date().getTime()
    this._duration = opt.duration
    this.addToMaterials(opt)
  }

  addToMaterials(options) {
    if (!defined(Material._materialCache._temp)) {
      Material._materialCache._temp = 0
    }
    const temp_index = ++Material._materialCache._temp
    const materialType = `Animation_${temp_index}_Type`
    Material._materialCache.addMaterial(materialType, {
      fabric: {
        type: materialType,
        uniforms: {
          image: options.url,
          color: new Color(1.0, 0.0, 0.0, 1),
          time: 0,
          repeat: options.repeat,
          axisY: options.axisY
        },
        source: source
      },
      translucent: function () {
        return !0
      }
    })
    this._materialImage = options.url
    this._materialType = materialType
    this._materialRepeat = options.repeat
  }

  _getOptions(options) {
    return Object.assign(
      {
        color: Color.WHITE,
        duration: 1000,
        url: this._getDefaultImage(),
        repeat: new Cartesian2(1, 1),
        axisY: false
      },
      options
    )
  }

  _getDefaultImage() {
    const ramp = document.createElement('canvas')
    ramp.width = 512
    ramp.height = 32
    const ctx = ramp.getContext('2d')
    const grd = ctx.createLinearGradient(0, 0, 512, 0)
    grd.addColorStop(0, '#ffffff00')
    grd.addColorStop(1, '#ffff00')
    ctx.fillStyle = grd
    ctx.fillRect(0, 0, 512, 32)
    return ramp.toDataURL()
  }

  get isConstant() {
    return false
  }

  get definitionChanged() {
    return this._definitionChanged
  }

  getType() {
    return this._materialType
  }

  get type() {
    return this._materialType
  }

  get source() {
    return source
  }

  getValue(time, result) {
    if (!defined(result)) {
      result = {}
    }
    result.color = Property.getValueOrClonedDefault(this._color, time, Color.WHITE, result.color)
    result.image = this._materialImage
    result.time = ((new Date().getTime() - this._time) % this._duration) / this._duration
    result.repeat = this._materialRepeat
    return result
  }

  equals(other) {
    return this === other || (other instanceof AnimationMaterialProperty && Property.equals(this._color, other._color))
  }
}
defineProperties(AnimationMaterialProperty.prototype, {
  color: createPropertyDescriptor('color')
})

export { AnimationMaterialProperty }
